package org.paboo.chart.code128;

import com.google.gson.Gson;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import org.paboo.entity.ImageEntity;
import org.paboo.http.BaseServlet;
import org.paboo.http.HttpMethod;
import org.paboo.util.LoggerFactoryUtils;
import org.paboo.util.ParameterObject;
import org.paboo.util.ZxingImage;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

public class Code128Servlet extends BaseServlet {

    private static final long serialVersionUID = -8770983696806841283L;
    private LoggerFactoryUtils log = LoggerFactoryUtils.getInstance().load(getClass());

    @Override
    protected void processRequest(HttpServletRequest request, HttpServletResponse response, HttpMethod method)
            throws ServletException, IOException {
        Code128Entity p = new Code128Entity();
        if (method == HttpMethod.GET) {
            String ctx = getParameterWithDefault(request, "data", ParameterObject.DEFAULT_CONTECT);
            String encoding = StandardCharsets.UTF_8.name();
            ctx = URLDecoder.decode(ctx, encoding);
            ctx = new String(ctx.getBytes(encoding), StandardCharsets.ISO_8859_1);
            p.setData(ctx);

            p.setFormat(getParameterWithDefault(request, "format", "png"));
            String[] size = getParameterWithDefault(request, "size", "128x64").split("x");
            p.setWidth(Integer.valueOf(size[0]));
            p.setHeight(Integer.valueOf(size[1]));
        } else if (method == HttpMethod.POST) {
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(request.getInputStream(), request.getCharacterEncoding()));
            Gson gson = new Gson();
            p = gson.fromJson(br, Code128Entity.class);
            if (!ParameterObject.hasText(p.getData())) {
                p.setData(ParameterObject.DEFAULT_CONTECT);
            }
            if (!ParameterObject.hasText(p.getFormat())) {
                p.setFormat("png");
            }
            if (!ParameterObject.hasInteger(p.getWidth()) || !ParameterObject.hasInteger(p.getWidth())) {
                p.setHeight(64);
                p.setWidth(128);
            }
            log.info(gson.toJson(p));
        } else {
            response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "Request error!!!");
            return;
        }

        BitMatrix matrix;
        try {
            matrix = new Code128Writer().encode(p.getData(), BarcodeFormat.CODE_128, p.getWidth(), p.getHeight());
            log.debug("Matrix size:" + matrix.getWidth() + "x" + matrix.getHeight());
        } catch (Exception e) {
            String errorMsg = "Create Fail!!!";
            if (log.isDebugEnabled()) {
                log.error(errorMsg, e);
            } else {
                log.error(errorMsg);
            }
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
            return;
        }

//        if ("svg".equalsIgnoreCase(p.getFormat())) {
//            try {
//                response.setContentType("image/svg+xml");
//                ZxingImage.toSVGDocument(matrix,
//                        new OutputStreamWriter(new BufferedOutputStream(response.getOutputStream()), StandardCharsets.ISO_8859_1.name()),
//                        new ImageEntity(p.getHeight(), p.getWidth(), 0, ZxingImage.BLACK, ZxingImage.WHITE), 1);
//            } catch (Exception ex) {
//                String errorMsg = "Create Fail!!!";
//                if (log.isDebugEnabled()) {
//                    log.error(errorMsg, ex);
//                } else {
//                    log.error(errorMsg);
//                }
//                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
//            }
//            return;
//        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (!ImageIO.write(ZxingImage.toBufferedImage(matrix, ZxingImage.WHITE, ZxingImage.BLACK), p.getFormat(), out)) {
            log.error("Could not write an image of format " + p.getFormat());
            throw new IOException("Could not write an image of format " + p.getFormat());
        }
        response.setContentType("image/" + p.getFormat());
        response.setContentLength(out.size());
        response.getOutputStream().write(out.toByteArray());
    }

}
